home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume91 / utilitys / beav_132 / part06 / buffer.c next >
C/C++ Source or Header  |  1991-11-13  |  21KB  |  978 lines

  1. /*
  2. *       Buffer handling.
  3. */
  4.  
  5. #include    "def.h"
  6.  
  7. bool    onebuf ();
  8. bool    killablebufs ();
  9. bool    _yankbuffer ();
  10. char    next_buf ();
  11. bool    bclear ();
  12. bool    addline ();
  13. char    makelist ();
  14. bool    popblist ();
  15. char    listbuffers ();
  16. char    _killbuffer ();
  17. bool    _usebuffer ();
  18.  
  19. extern  ROW_FMT text_fmt;
  20. extern    char    MSG_use_b[];
  21. extern    char    MSG_kill_b[];
  22. extern    char    MSG_not_fnd[];
  23. extern    char    MSG_no_del_m[];
  24. extern    char    MSG_buf_disp[];
  25. extern    char    MSG_main[];
  26. extern    char    MSG_l_buf_h[];
  27. extern    char    MSG_l_buf_h1[];
  28. extern    char    MSG_no_chg[];
  29. extern    char    MSG_yank_b[];
  30. extern    char    MSG_no_buf[];
  31. extern    char    MSG_no_s_yank[];
  32. extern    char    MSG_buf_nam[];
  33. extern    char    MSG_bad_l[];
  34. extern    char    MSG_pick[];
  35. extern    char    MSG_siz_chg[];
  36. extern    char    MSG_no_siz_chg[];
  37. extern    char    MSG_up_arrow[];
  38. extern    char    MSG_null[];
  39. extern    char    MSG_save_buf[];
  40. extern    char    MSG_cnt_al_b[];
  41. extern    char    MSG_ins_cnt[];
  42.  
  43. BUFFER    sav_buf;
  44. LINE    sav_line_h;
  45. /*
  46. * Attach a buffer to a window. The
  47. * values of dot and mark come from the buffer
  48. * if the use count is 0. Otherwise, they come
  49. * from some other window.
  50. *
  51. * plus hacks for prev/next buffer and use-buffer-split  (jam)
  52. * functions (like in file.c)
  53. */
  54. char    usebuffer ()
  55. {
  56.  
  57.     char    bufn[NBUFN];
  58.     register char   s;
  59.  
  60.     if ((s = ereply (MSG_use_b, bufn, NBUFN, 0)) != TRUE)
  61.         return (s);
  62.     return (_usebuffer (bufn));
  63. }
  64.  
  65. /* use buffer, split window first
  66. */
  67. char    use_buffer ()
  68. {
  69.     char    bufn[NBUFN];
  70.     register char   s;
  71.  
  72.     if ((s = ereply (MSG_use_b, bufn, NBUFN, 0)) != TRUE)
  73.         return (s);
  74.     splitwind ();
  75.     return (_usebuffer (bufn));
  76. }
  77.  
  78. /* does all the work for changing to a new buffer for use-buffer,
  79. * use-buffer-split and prev-buff & next-buff
  80. */
  81. bool _usebuffer (bufn)
  82. char   *bufn;
  83. {
  84.     register    BUFFER * bp;
  85.     register    WINDOW * wp;
  86.  
  87.     if (strcmp (MSG_kill_b, bufn) == 0)/* hack! */
  88.         bp = blistp;
  89.     else
  90.         if ((bp = bfind (bufn, TRUE)) == NULL)
  91.             return (FALSE);
  92.  
  93.     /* if current buffer is special and new buffer is normal */
  94.     /* set to hex byte mode */
  95.     if ((curbp == blistp) && (R_TYPE(curwp) == TEXT))
  96.     {
  97.         dispsize1 ();
  98.         hexmode ();
  99.     }
  100.  
  101.     if (--curbp -> b_nwnd == 0)
  102.     {
  103.         /* Last use.         */
  104.         curbp -> b_dotp = curwp -> w_dotp;
  105.         curbp -> b_doto = curwp -> w_doto;
  106.         curbp -> b_unit_offset = curwp -> w_unit_offset;/* pvr */
  107.         curbp -> b_markp = curwp -> w_markp;
  108.         curbp -> b_marko = curwp -> w_marko;
  109.     }
  110.     curbp = bp;                 /* Switch.       */
  111.     curwp -> w_bufp = bp;
  112.     curwp -> w_linep = bp -> b_linep;/* For macros, ignored.     */
  113.     curwp -> w_loff = 0; /* pvr */
  114.     curwp -> w_flag |= WFMODE | WFFORCE | WFHARD;
  115.     /* Quite nasty.      */
  116.     if (bp -> b_nwnd++ == 0)
  117.     {
  118.         /* First use.        */
  119.         curwp -> w_dotp = bp -> b_dotp;
  120.         curwp -> w_doto = bp -> b_doto;
  121.         curwp -> w_unit_offset = 0;     /* pvr */
  122.         curwp -> w_markp = bp -> b_markp;
  123.         curwp -> w_marko = bp -> b_marko;
  124.         wind_on_dot (curwp);
  125.         /* if we are in the funny TEXT mode then goto standard HEX mode */
  126.         if (R_TYPE(curwp) == TEXT)
  127.             hexmode ();
  128.         return (TRUE);
  129.     }
  130.     wp = wheadp;                /* Look for old.     */
  131.     while (wp != NULL)
  132.     {
  133.         if (wp != curwp && wp -> w_bufp == bp)
  134.         {
  135.             curwp -> w_dotp = wp -> w_dotp;
  136.             curwp -> w_doto = wp -> w_doto;
  137.             curwp -> w_unit_offset = wp -> w_unit_offset;/* pvr */
  138.             curwp -> w_markp = wp -> w_markp;
  139.             curwp -> w_marko = wp -> w_marko;
  140.             break;
  141.         }
  142.         wp = wp -> w_wndp;
  143.     }
  144.     wind_on_dot (curwp);
  145.     /* if we are in the funny TEXT mode then goto standard HEX mode */
  146.     if (R_TYPE(curwp) == TEXT)
  147.         hexmode ();
  148.     return (TRUE);
  149. }
  150.  
  151.  
  152. /*
  153. * Dispose of a buffer, by name.
  154. * Ask for the name. Look it up (don't get too
  155. * upset if it isn't there at all!). Get quite upset
  156. * if the buffer is being displayed. Clear the buffer (ask
  157. * if the buffer has been changed). Then free the header
  158. * line and the buffer header. Bound to "C-X K".
  159. */
  160. char    killbuffer ()
  161. {
  162.     register char   s;
  163.     char    bufn[NBUFN];
  164.  
  165.     if ((s = ereply (MSG_kill_b, bufn, NBUFN, 0)) != TRUE)
  166.         return (s);
  167.     if (s = _killbuffer (bufn))
  168.         writ_echo (okmsg);             /* verbose-ness (jam) */
  169.     return (s);
  170. }
  171.  
  172.  
  173. char    _killbuffer (bufn)
  174. char   *bufn;
  175. {
  176.     register    BUFFER * bp,
  177.     *bp1,
  178.     *bp2;
  179.     register char   s,
  180.     x = 0;
  181.  
  182.     if (((bp = bfind (bufn, FALSE)) == NULL) ||
  183.         !strcmp (bufn, MSG_save_buf))
  184.     {
  185.         writ_echo (MSG_not_fnd);
  186.         return (FALSE);
  187.     }
  188.  
  189.  
  190.     if (killablebufs (bp))      /* can't kill '?' if no other buffers */
  191.     {
  192.         writ_echo (MSG_no_del_m);
  193.         return (FALSE);
  194.     }
  195.  
  196.     /* see if the buffer to be killed is in a window */
  197.     bp1 = bp;
  198.     if (curbp == blistp && onebuf (bp))/* Hack ! */
  199.     {
  200.         next_buf ();
  201.         onlywind ();
  202.         update ();
  203.     }
  204.  
  205.     if (bp -> b_nwnd > 0)
  206.     {
  207.         if ((s = eyesno (MSG_buf_disp)) != TRUE)
  208.             return (s);
  209.  
  210.         /* make the current window the only window if it is to die */
  211.         onlywind ();
  212.         if (curbp == bp)
  213.         {
  214.             next_buf ();
  215.             if (curbp == bp)
  216.                 x++;
  217.         }
  218.     }
  219.     if ((s = bclear (bp)) != TRUE)/* Blow text away.      */
  220.     {
  221.         if (bp1 == blistp)      /* special buffer */
  222.             curbp = bp1;
  223.         else
  224.             if (!x)
  225.                 _usebuffer (bp1 -> b_bname);
  226.         /* back to original buffer (jam) */
  227.         return (s);
  228.     }
  229.     if (x)
  230.     {
  231.         _usebuffer (MSG_main);
  232.         x++;
  233.     }
  234.  
  235.     free ((char *) bp -> b_linep);/* Release header line.         */
  236.     bp1 = NULL;                 /* Find the header.     */
  237.     bp2 = bheadp;
  238.     while (bp2 != bp)
  239.     {
  240.         bp1 = bp2;
  241.         bp2 = bp2 -> b_bufp;
  242.     }
  243.     bp2 = bp2 -> b_bufp;        /* Next one in chain.   */
  244.     if (bp1 == NULL)            /* Unlink it.           */
  245.         bheadp = bp2;
  246.     else
  247.         bp1 -> b_bufp = bp2;
  248.     free ((char *) bp);         /* Release buffer block         */
  249.     if (x)
  250.         update ();
  251.     /* update buffer display */
  252.     if ((blistp -> b_nwnd != 0) &&
  253.         (blistp -> b_type == BTLIST))
  254.         listbuffers ();
  255.     return (TRUE);
  256. }
  257.  
  258. /*
  259. * Display the buffer list. This is done
  260. * in two parts. The "makelist" routine figures out
  261. * the text, and puts it in the buffer whoses header is
  262. * pointed to by the external "blistp". The "popblist"
  263. * then pops the data onto the screen. Bound to
  264. * "C-X C-B".
  265. */
  266. char    listbuffers ()
  267. {
  268.     register char   s;
  269.  
  270.     if ((s = makelist ()) != TRUE)
  271.         return (s);
  272.     return (popblist ());
  273. }
  274. /*
  275. * Display the save buffer contents.
  276. * Bound to "Meta C-W".
  277. */
  278. char    showsavebuf ()
  279. {
  280.     WINDOW   *wp;
  281.  
  282.     if (sav_buf.b_nwnd == 0)
  283.     {
  284.         splitwind ();
  285.         _usebuffer (MSG_save_buf);
  286.     }
  287.     else
  288.     {
  289.         wp = wheadp;                /* Look for old.     */
  290.         while (wp != NULL)
  291.         {
  292.             if (wp -> w_bufp == &sav_buf)
  293.             {
  294.                 wp -> w_flag |= WFMODE | WFFORCE | WFHARD;
  295.                 break;
  296.             }
  297.             wp = wp -> w_wndp;
  298.         }
  299.     }
  300.     return (TRUE);
  301. }
  302.  
  303. /*
  304. * Pop the special buffer whose
  305. * buffer header is pointed to by the external
  306. * variable "blistp" onto the screen. This is used
  307. * by the "listbuffers" routine (above) and by
  308. * some other packages. Returns a status.
  309. */
  310. bool popblist ()
  311. {
  312.     register    WINDOW * wp;
  313.     register    BUFFER * bp;
  314.  
  315.     if (blistp -> b_nwnd == 0)  /* Not on screen yet.    */
  316.     {
  317.         if ((wp = wpopup ()) == NULL)
  318.             return (FALSE);
  319.         bp = wp -> w_bufp;
  320.         if (--bp -> b_nwnd == 0)
  321.         {
  322.             bp -> b_dotp = wp -> w_dotp;
  323.             bp -> b_doto = wp -> w_doto;
  324.             bp -> b_unit_offset = wp -> w_unit_offset;/* pvr */
  325.             bp -> b_markp = wp -> w_markp;
  326.             bp -> b_marko = wp -> w_marko;
  327.         }
  328.         curwp = wp;
  329.         curbp = blistp;
  330.         wp -> w_bufp = blistp;
  331.         ++blistp -> b_nwnd;
  332.     }
  333.     wp = wheadp;
  334.     while (wp != NULL)
  335.     {
  336.         if (wp -> w_bufp == blistp)
  337.         {
  338.             wp -> w_linep = lforw (blistp -> b_linep);
  339.             wp -> w_loff = 0;
  340.             wp -> w_dotp = lforw (blistp -> b_linep);
  341.             wp -> w_doto = 0;
  342.             wp -> w_unit_offset = 0;
  343.             wp -> w_markp = NULL;
  344.             wp -> w_marko = 0;
  345.             wp -> w_disp_shift = 0;
  346.             wp -> w_intel_mode = FALSE;
  347.             wp -> w_fmt_ptr = &text_fmt;
  348.             wp -> w_flag |= WFMODE | WFHARD;
  349.         }
  350.         wp = wp -> w_wndp;
  351.     }
  352.     return (TRUE);
  353. }
  354.  
  355. /*
  356. * This routine rebuilds the
  357. * text in the special secret buffer
  358. * that holds the buffer list. It is called
  359. * by the list buffers command. Return TRUE
  360. * if everything works. Return FALSE if there
  361. * is an error (if there is no memory).
  362. */
  363. char    makelist ()
  364. {
  365.     register    char  *cp1;
  366.     register    char  *cp2;
  367.     register    int    c;
  368.     register    BUFFER * bp;
  369.     register    A32    nbytes;
  370.     register    char   s;
  371.     char    b[8 + 1];
  372.     char    line[128];
  373.  
  374.     blistp -> b_flag &= ~BFCHG; /* Blow away old.    */
  375.     if ((s = bclear (blistp)) != TRUE)
  376.         return (s);
  377.     blistp -> b_flag |= BFVIEW;
  378.     blistp -> b_type = BTLIST;
  379.     strcpy (blistp -> b_fname, MSG_up_arrow);
  380.     if (addline (MSG_l_buf_h) == FALSE
  381.         || addline (MSG_l_buf_h1) == FALSE)
  382.         return (FALSE);
  383.     bp = bheadp;                /* For all buffers   */
  384.     while (bp != NULL)
  385.     {
  386.         cp1 = &line[0];         /* Start at left edge    */
  387.         if ((bp -> b_flag & BFCHG) != 0)/* "*" if changed    */
  388.             *cp1++ = '*';
  389.         else
  390.             if (bp -> b_flag & BFVIEW)/* jam */
  391.                 *cp1++ = 'R';   /* readonly */
  392.             else
  393.                 *cp1++ = ' ';
  394.         *cp1++ = ' ';           /* Gap. */
  395.         if ((bp -> b_flag & BFBAD) != 0)/* "?" if maybe trashed  */
  396.             *cp1++ = '?';
  397.         else
  398.             *cp1++ = ' ';
  399.         *cp1++ = ' ';           /* Gap. */
  400.         nbytes = bp -> b_linep -> l_bp -> l_file_offset +
  401.             bp -> b_linep -> l_bp -> l_used;
  402.         sprintf (b, "%8lx", nbytes); /* 8 digit buffer size.   */
  403.         cp2 = &b[0];
  404.         while ((c = *cp2++) != 0)
  405.             *cp1++ = c;
  406.         *cp1++ = ' ';           /* Gap.          */
  407.         cp2 = &bp -> b_bname[0];/* Buffer name       */
  408.         while ((c = *cp2++) != 0)
  409.             *cp1++ = c;
  410.         *cp1++ = ' ';           /* Gap.          */
  411.         *cp1++ = ' ';           /* Gap.          */
  412.         cp2 = &bp -> b_fname[0];/* File name         */
  413.         if (*cp2 != 0)
  414.         {
  415.             while (cp1 < &line[1 + 1 + 1 + 1 + 6 + 1 + NBUFN + 1])
  416.                 *cp1++ = ' ';
  417.             while ((c = *cp2++) != 0)
  418.             {
  419.                 if (cp1 < &line[128 - 1])
  420.                     *cp1++ = c;
  421.             }
  422.         }
  423.         while (cp1 < &line[80])   /* Fill out line to col 80 */
  424.             *cp1++ = ' ';
  425.  
  426.         *cp1 = 0;               /* Add to the buffer.    */
  427.         if (addline (line) == FALSE)
  428.             return (FALSE);
  429.         bp = bp -> b_bufp;
  430.     }
  431.     return (TRUE);              /* All done      */
  432. }
  433.  
  434. /*
  435. * The argument "text" points to
  436. * a string. Append this line to the
  437. * buffer list buffer. 
  438. * Return TRUE if it worked and
  439. * FALSE if you ran out of room.
  440. */
  441. bool addline (text)
  442. char   *text;
  443. {
  444.     register    LINE    * lp;
  445.     register    int     i, allocsize;
  446.     register    int     ntext;
  447.  
  448.     ntext = strlen (text);
  449.     allocsize = 128;
  450.  
  451.     if ((lp = lalloc (allocsize)) == NULL)
  452.         return (FALSE);
  453.  
  454.     for (i = 0; i < ntext; ++i)
  455.         lputc (lp, i, text[i]);
  456.  
  457.     for (; i < allocsize; ++i)     /* fill out line with spaces */
  458.         lputc (lp, i, ' ');
  459.  
  460.     blistp -> b_linep -> l_bp -> l_fp = lp;/* Hook onto the end  */
  461.     lp -> l_bp = blistp -> b_linep -> l_bp;
  462.     blistp -> b_linep -> l_bp = lp;
  463.     lp -> l_fp = blistp -> b_linep;
  464.     lp -> l_size = allocsize;  /* line size is limited to 80 chars */
  465.     lp -> l_used = allocsize;
  466.     lp -> l_file_offset = lp -> l_bp -> l_file_offset + lp -> l_bp -> l_used;
  467.     if (blistp -> b_dotp == blistp -> b_linep)/* If "." is at the end    */
  468.         blistp -> b_dotp = lp;  /* move it to new line   */
  469.     return (TRUE);
  470. }
  471.  
  472.  
  473. /*
  474. * Look through the list of
  475. * buffers. Return TRUE if there
  476. * are any changed buffers. Special buffers
  477. * like the buffer list buffer don't count, as
  478. * they are not in the list. Return FALSE if
  479. * there are no changed buffers.
  480. */
  481. bool anycb ()
  482. {
  483.     register    BUFFER * bp;
  484.  
  485.     bp = bheadp;
  486.     while (bp != NULL)
  487.     {
  488.  
  489.         if ((bp -> b_flag & BFCHG) != 0)
  490.             return (TRUE);
  491.         bp = bp -> b_bufp;
  492.     }
  493.     return (FALSE);
  494. }
  495.  
  496.  
  497. /*
  498. * Search for a buffer, by name.
  499. * If not found, and the "cflag" is TRUE,
  500. * create a buffer and put it in the list of
  501. * all buffers. Return pointer to the BUFFER
  502. * block for the buffer.
  503. */
  504. BUFFER * bfind (bname, cflag)
  505. register char  *bname;
  506. {
  507.     register    BUFFER * bp;
  508.  
  509.     bp = bheadp;
  510.     while (bp != NULL)
  511.     {
  512.         if (strcmp (bname, bp -> b_bname) == 0)
  513.             return (bp);
  514.         bp = bp -> b_bufp;
  515.     }
  516.     if (cflag != FALSE && (bp = bcreate (bname)) != NULL)
  517.     {
  518.         bp -> b_bufp = bheadp;
  519.         bheadp = bp;
  520.     }
  521.     return (bp);
  522. }
  523.  
  524.  
  525. /*
  526. * Create a buffer, by name.
  527. * Return a pointer to the BUFFER header
  528. * block, or NULL if the buffer cannot
  529. * be created. The BUFFER is not put in the
  530. * list of all buffers; this is called by
  531. * "edinit" to create the buffer list
  532. * buffer.
  533. */
  534. BUFFER * bcreate (bname)
  535. register char  *bname;
  536. {
  537.  
  538.     register    BUFFER * bp;
  539.     register    LINE * lp;
  540.  
  541.     if ((bp = (BUFFER *) malloc (sizeof (BUFFER))) == NULL)
  542.     {
  543.         err_echo (MSG_cnt_al_b);
  544.         return (NULL);
  545.     }
  546.     if ((lp = lalloc (0)) == NULL)
  547.     {
  548.         free ((char *) bp);
  549.         return (NULL);
  550.     }
  551.     bp -> b_bufp = NULL;
  552.     bp -> b_dotp = lp;
  553.     bp -> b_doto = 0;
  554.     bp -> b_unit_offset = 0;    /* unit offset   pvr */
  555.     bp -> b_markp = NULL;
  556.     bp -> b_marko = 0;
  557.     bp -> b_flag = 0;
  558.     bp -> b_nwnd = 0;
  559.     bp -> b_linep = lp;
  560.     strcpy (bp -> b_fname, MSG_null);
  561.     strcpy (bp -> b_bname, bname);
  562.     lp -> l_fp = lp;
  563.     lp -> l_bp = lp;
  564.     lp -> l_file_offset = 0;    /* pvr */
  565.     lp -> l_used = 0;           /* pvr */
  566.     lp -> l_size = 0;           /* size of zero indicates the header line  pvr 
  567.                                                         */
  568.     return (bp);
  569. }
  570.  
  571.  
  572. /*
  573. * This routine blows away all of the text
  574. * in a buffer. If the buffer is marked as changed
  575. * then we ask if it is ok to blow it away; this is
  576. * to save the user the grief of losing text. The
  577. * window chain is nearly always wrong if this gets
  578. * called; the caller must arrange for the updates
  579. * that are required. Return TRUE if everything
  580. * looks good.
  581. */
  582. bool bclear (bp)
  583. register    BUFFER * bp;
  584. {
  585.     register    LINE * lp;
  586.     register char   s;
  587.  
  588.     if ((bp -> b_flag & BFCHG) != 0/* Changed.       */
  589.     && (s = eyesno (MSG_no_chg)) != TRUE)
  590.         return (s);
  591.     bp -> b_flag &= ~BFCHG;     /* Not changed       */
  592.     while ((lp = lforw (bp -> b_linep)) != bp -> b_linep)
  593.         lfree (lp);
  594.     bp -> b_dotp = bp -> b_linep;/* Fix "."      */
  595.     bp -> b_doto = 0;
  596.     bp -> b_unit_offset = 0;    /* pvr */
  597.     bp -> b_markp = NULL;       /* Invalidate mark  */
  598.     bp -> b_marko = 0;
  599.     return (TRUE);
  600. }
  601.  
  602.  
  603. /* flip to next buffer in the list, wrap
  604. * to beginning if required (wrap around)
  605. * (skips buffers saved  by save-region)  
  606. */
  607. char    next_buf ()
  608. {
  609.     register    BUFFER * bp;
  610.  
  611.     bp = curbp;
  612.     while (TRUE)
  613.     {
  614.         if (!(bp = bp -> b_bufp))
  615.             bp = bheadp;
  616.         if ((bp -> b_type == BTSAVE) ||
  617.             (bp -> b_type == BTLIST) ||
  618.             (bp -> b_type == BTHELP))
  619.             continue;
  620.         break;
  621.     }
  622.     _usebuffer (bp -> b_bname);
  623.     return (TRUE);
  624. }
  625.  
  626.  
  627. /* flip to prev buffer in the list, wrap
  628. * to end if required (wrap around)
  629. * (does NOT skip buffers saved by save-region)  
  630. */
  631. char    prev_buf ()
  632. {
  633.     register    BUFFER * sp;
  634.  
  635.     if ((sp = curbp) == bheadp) /* front of list */
  636.     {
  637.         for (; sp -> b_bufp; sp = sp -> b_bufp)
  638.             ;
  639.     }
  640.     else /* cycle around */
  641.     {
  642.         for (sp = bheadp; sp -> b_bufp; sp = sp -> b_bufp)
  643.         {
  644.             if (sp -> b_bufp == curbp)
  645.                 break;
  646.         }
  647.     }
  648.     return (_usebuffer (sp -> b_bname));
  649. }
  650.  
  651.  
  652. /* yank a buffer into current buffer
  653. */
  654. char    yank_buffer ()
  655. {
  656.     char    bufn[NBUFN];
  657.  
  658.     if (ereply (MSG_yank_b, bufn, NBUFN, 0) != TRUE)
  659.         return (FALSE);
  660.     return (_yankbuffer (bufn));
  661. }
  662.  
  663.  
  664. bool _yankbuffer (bufn)
  665. char   *bufn;
  666. {
  667.     register    LINE * lp;
  668.     register    BUFFER * bp = curbp;
  669.     register int    s;
  670.     A32      cnt;
  671.     char        buf[NFILEN], buf1[NFILEN];
  672.  
  673.     if ((bp = bfind (bufn, FALSE)) == NULL)
  674.     {
  675.         writ_echo (MSG_no_buf);
  676.         return (FALSE);
  677.     }
  678.     if (strcmp (bp -> b_bname, curbp -> b_bname) == 0)
  679.     {
  680.         writ_echo (MSG_no_s_yank);
  681.         return (FALSE);
  682.     }
  683.     cnt = 0;
  684.     lp = lforw (bp -> b_linep);
  685.     while (TRUE)
  686.     {
  687.         cnt += lp -> l_used;
  688.         for (s = 0; s < lp -> l_used; s++)
  689.             if (linsert (1, lp -> l_text[s]) == FALSE)
  690.                 return (FALSE);
  691.  
  692.         if ((lp = lforw (lp)) == bp -> b_linep)
  693.         {
  694.             break;
  695.         }
  696.  
  697.         if ((cnt & 0x7ff) == 0)
  698.         {
  699.             sprintf (buf1, MSG_ins_cnt, R_POS_FMT(curwp));
  700.             sprintf (buf, buf1, cnt);
  701.             writ_echo (buf);
  702.             /* check if we should quit */
  703.             if (ttkeyready ())
  704.             {
  705.                 l_fix_up (lp -> l_bp);
  706.                 wind_on_dot_all();
  707.                 if (ttgetc () == CTL_G)  /* was it an abort key? */
  708.                     return (FALSE);
  709.             }
  710.         }
  711.     }
  712.     writ_echo (okmsg);
  713.     return (TRUE);
  714. }
  715.  
  716.  
  717. bool buffername ()
  718. {
  719.  
  720.     register    WINDOW * wp;
  721.     register char  *p;
  722.     register char   s;
  723.     char    bname[NBUFN + 1];
  724.  
  725.     if ((s = ereply (MSG_buf_nam, bname, NBUFN, 0)) == ABORT)
  726.         return (s);
  727.     for (p = bname; *p && *p != ' '; p++)
  728.         ;
  729.     *p = 0;                     /* no blanks */
  730.     strcpy (curbp -> b_bname, bname);
  731.     wp = wheadp;                /* Update mode lines.   */
  732.     while (wp != NULL)
  733.     {
  734.         if (wp -> w_bufp == curbp)
  735.             wp -> w_flag |= WFMODE;
  736.         wp = wp -> w_wndp;
  737.     }
  738.     if ((blistp -> b_nwnd != 0) &&  /* update buffer display */
  739.     (blistp -> b_type == BTLIST))
  740.         listbuffers ();
  741.     return (TRUE);
  742. }
  743.  
  744.  
  745. /* any killable buffers around ? (jam)
  746. */
  747. bool killablebufs (bp)
  748. register    BUFFER * bp;
  749. {
  750.     if (strcmp (bp -> b_bname, MSG_main) == 0)/* doomed buffer is 'empty' */
  751.         if (bheadp == bp)       /* and is only buffer in list */
  752.             if (bheadp -> b_bufp == 0)/* then there are no killable buffers */
  753.                 return (TRUE);
  754.     return (FALSE);
  755. }
  756.  
  757.  
  758. /* only 1 buffer around ?
  759. */
  760. bool onebuf (bp)
  761. register    BUFFER * bp;
  762. {
  763.     if (strcmp (bp -> b_bname, bheadp -> b_bname) == 0)
  764.         if (bheadp -> b_bufp == 0)
  765.             return (TRUE);
  766.     return (FALSE);
  767. }
  768.  
  769.  
  770. /* funky new name; real yukky!!!! (jam) 
  771. */
  772. void funky_name (bname, n)
  773. register char  *bname;
  774. int     n;
  775. {
  776.     char    num[10];
  777.     register int    i;
  778.     register char  *p;
  779.  
  780.     for (i = 0; i < 10; i++)
  781.         num[i] = ' ';
  782.     for (p = bname; *p; p++)
  783.         *p = 0;
  784.     *bname++ = '#';
  785.     sprintf (num, "%lx", (long) n + 1);
  786.     for (p = num; *p; p++)
  787.         if (*p != ' ')
  788.             *bname++ = *p;
  789.     *bname = 0;
  790. }
  791.  
  792.  
  793. /* pick a buffer to goto/kill
  794. */
  795. #define BUFFEROFFSET (13)       /* depends on makelist !! */
  796.  
  797. bool pickone ()
  798. {
  799.     register int    s,
  800.     i,
  801.     c;
  802.     register    LINE * lp;
  803.     char    name[NBUFN + 1];
  804.     char    buf[3];
  805.     WINDOW  *wp;
  806.  
  807.     lp = curwp -> w_dotp;       /* get the buffer name from the line */
  808.  
  809.     i = 0;
  810.     if (!llength (lp))
  811.     {
  812.         writ_echo (MSG_bad_l);
  813.         return (FALSE);
  814.     }
  815.     for (s = BUFFEROFFSET; (c = lgetc (lp, s)) != ' '; s++)
  816.     {
  817.         name[i++] = c;
  818.         if (s >= llength (lp))
  819.             break;
  820.     }
  821.     name[i] = 0;
  822.     if (!bfind (name, FALSE))
  823.     {
  824.         writ_echo (MSG_bad_l);
  825.         return (FALSE);
  826.     }
  827. loop:
  828.     if ((s = ereply (MSG_pick, buf, 2, name)) != TRUE)
  829.         return (FALSE);
  830.     if (ISLOWER (buf[0]) != FALSE)
  831.         buf[0] = TOUPPER (buf[0]);
  832.     if (buf[0] == 'K')
  833.         _killbuffer (name);
  834.     else
  835.         if (buf[0] == 'G')
  836.             _usebuffer (name);
  837.         else
  838.             if (buf[0] == 'S')
  839.             {
  840.                 _usebuffer (name);
  841.                 /* goto this buffer, but don't show the user */
  842.                 filesave ();
  843.                 _usebuffer (MSG_kill_b);
  844.                 /* jump back to this window - HACK ! */
  845.                 listbuffers (); /* update the list */
  846.             }
  847.             else
  848.                 goto loop;
  849.     writ_echo (MSG_null);
  850.     return (TRUE);
  851. }
  852. /*
  853. *   Toggle the buffer size lock bit.
  854. */
  855. char bufsizlock ()
  856. {
  857.     if (curbp -> b_flag & BFSLOCK)
  858.     {
  859.         curbp -> b_flag &= ~BFSLOCK;
  860.         writ_echo (MSG_siz_chg);
  861.     }
  862.     else
  863.     {
  864.         if (insert_mode)
  865.             insert_toggle ();
  866.         curbp -> b_flag |= BFSLOCK;
  867.         writ_echo (MSG_no_siz_chg);
  868.     }
  869.     return (TRUE);
  870. }
  871.  
  872. /*
  873.  *   Append the given line to the end of the given buffer.
  874.  */
  875. void   b_append_l (buf_p, lp)
  876. BUFFER *buf_p;
  877. LINE   *lp;
  878. {
  879.     LINE   *h_lp;
  880.  
  881.     h_lp = buf_p -> b_linep;
  882.  
  883.     lp -> l_fp = h_lp;
  884.     lp -> l_bp = h_lp -> l_bp;
  885.     lp -> l_bp -> l_fp = lp;
  886.     h_lp -> l_bp = lp;
  887.     lp -> l_file_offset = lp -> l_bp -> l_file_offset + lp -> l_bp -> l_used;
  888. }
  889. /*
  890.  *   Append the given line to the end of the given buffer.
  891.  */
  892. bool   b_append_c (buf_p, ch)
  893. BUFFER *buf_p;
  894. D8     ch;
  895. {
  896.     LINE   *lp;
  897.  
  898.     lp = buf_p -> b_linep -> l_bp;    /* get last line */
  899.     /* do I need to get a new line? */
  900.     if (lp -> l_size <= lp -> l_used)
  901.     {
  902.         if ((lp = lalloc (KBLOCK)) == NULL)
  903.             return (FALSE);
  904.  
  905.         lp -> l_fp = buf_p -> b_linep;
  906.         lp -> l_bp = buf_p -> b_linep -> l_bp;
  907.         lp -> l_bp -> l_fp = lp;
  908.         buf_p -> b_linep -> l_bp = lp;
  909.     }
  910.     lp -> l_text[lp -> l_used++] = ch;
  911.  
  912.     return (TRUE);
  913. }
  914.  
  915. /*
  916.  * Initialize the save buffer.
  917.  */
  918. void save_buf_init ()
  919. {
  920.     register    BUFFER * bp;
  921.  
  922.     sav_line_h.l_fp = &sav_line_h;
  923.     sav_line_h.l_bp = &sav_line_h;
  924.     sav_line_h.l_file_offset = 0;
  925.     sav_line_h.l_used = 0;
  926.     sav_line_h.l_size = 0;
  927.  
  928.     sav_buf.b_type = BTSAVE;
  929.     sav_buf.b_bufp = NULL;
  930.     sav_buf.b_dotp = &sav_line_h;
  931.     sav_buf.b_doto = 0;
  932.     sav_buf.b_unit_offset = 0;
  933.     sav_buf.b_markp = NULL;
  934.     sav_buf.b_marko = 0;
  935.     sav_buf.b_linep = &sav_line_h;
  936.     sav_buf.b_nwnd = 0;
  937.     sav_buf.b_flag = BFVIEW;
  938.     sav_buf.b_begin_addr = 0;
  939.     sav_buf.b_file_size = 0;
  940.     sav_buf.b_fname[0] = 0;
  941.     strcpy (sav_buf.b_bname, MSG_save_buf);
  942.  
  943.     /* put on end of chain */
  944.     bp = bheadp;
  945.     while ((bp -> b_bufp) != NULL)
  946.         bp = bp -> b_bufp;
  947.  
  948.     bp->b_bufp = &sav_buf;
  949.  
  950. }
  951.  
  952. /*
  953.  * Set the save buffer dot pointer to the begining.
  954.  */
  955. void save_buf_home ()
  956. {
  957.     sav_buf.b_dotp = sav_buf.b_linep -> l_fp;
  958.     sav_buf.b_doto = 0;
  959.     sav_buf.b_flag = BFVIEW;
  960. }
  961.  
  962. D16  get_save_char ()
  963. {
  964.     D8 ch;
  965.  
  966.     /* are we past the end of the buffer */
  967.     if (sav_buf.b_dotp == sav_buf.b_linep)
  968.         return (-1);
  969.     ch = sav_buf.b_dotp -> l_text[sav_buf.b_doto++];
  970.     if (sav_buf.b_doto >= sav_buf.b_dotp -> l_used)
  971.     {
  972.         sav_buf.b_doto = 0;
  973.         sav_buf.b_dotp = sav_buf.b_dotp -> l_fp;
  974.     }
  975.     return ((D16)ch);
  976. }
  977.  
  978.